//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Linea.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

Linea::~Linea(){
        delete origen;
        delete destino;
}

Linea * Linea::copiar(){

        PV* o=this->origen->copiar();
        PV* d=this->destino->copiar();
        return new Linea(o,d);



}
void Linea::mover(PV* p){
        origen->suma(origen,p);
        destino->suma(destino,p);

}
bool Linea::igual(Linea  * l){
  if(this->origen->igual(l->getOrigen()))
    if(this->destino->igual(l->getDestino()))
      return true;
  return false;

}

//---------------------------------------------------------------------------
void Linea::draw(){

    Lapiz * l = new Lapiz(origen,0);
    l->lineTo(destino);
    delete l;

}
//---------------------------------------------------------------------------
bool  Linea::guarda(ofstream & Archivo){
     //punto de origen
           origen->guarda(Archivo);
     //punto de destino
           destino->guarda(Archivo);

     return Archivo.good();
}
//---------------------------------------------------------------------------
bool  Linea::abre(ifstream & Archivo){
     //punto de origen
        origen->abre(Archivo);
     //punto de destino
        destino->abre(Archivo);

     return Archivo.good();
}
//-------------------------------------------------------
bool Linea::recortar(PV * p1,PV * p2){
        GLubyte codO, codD;
        codO = 0;
        GLfloat l,r,t,b;
        l = min(p1->getX(),p2->getX());
        r = max(p1->getX(),p2->getX());
        b = min(p1->getY(),p2->getY());
        t = max(p1->getY(),p2->getY());

        GLubyte codL = 8;
        GLubyte codT = 4;
        GLubyte codR = 2;
        GLubyte codB = 1;

        //orden de los bits del codigo:
        // izq,arriba,derecha,abajo
        codO = codigoCohen(origen,l,t,r,b);
        codD = codigoCohen(destino,l,t,r,b);

        
        //si los dos puntos son internos al rectangulo la linea
        //no se modifica. CODS == 0
        if(codD == 0 && codO == 0){
                return false;                 }


        //si en el mismo semiplano tienen el codigo a 1, la recta es eliminable
        if((codD & codO) != 0){
                return true;
        }

        try{
        //resto de casos, o caso general
        while(!(codD == 0 && codO == 0)){
              //punto origen
              if (codO != 0){
                 //izq.
                    if((codO & codL) != 0){
                      origen->setY(origen->getY() -
                                 ( (origen->getX() - l) *
                                  (origen->getY() - destino->getY()) /
                                  (origen->getX() - destino->getX())));
                      origen->setX(l);
                    }
                 //arriba
                    if((codO & codT) != 0){
                      origen->setX(origen->getX() -
                                 ( (origen->getY() - t) *
                                  (origen->getX() - destino->getX()) /
                                  (origen->getY() - destino->getY())));
                      origen->setY(t);
                    }
                 //derecha
                    if((codO & codR) != 0){
                      origen->setY(origen->getY() -
                                 ( (origen->getX() - r) *
                                  (origen->getY() - destino->getY()) /
                                  (origen->getX() - destino->getX())));
                      origen->setX(r);
                    }
                 //abajo
                    if((codO & codB) != 0){
                       origen->setX(origen->getX() -
                                 ( (origen->getY() - b) *
                                  (origen->getX() - destino->getX()) /
                                  (origen->getY() - destino->getY())));
                      origen->setY(b);
                    }
              }
              codO = codigoCohen(origen,l,t,r,b);

              if  ((codD != 0 && codO != 0)){
                        return true;
              }
              
              //punto destino
              if (codD != 0){
                  //izq.
                    if((codD & codL) != 0){
                      destino->setY(destino->getY() -
                                 ( (destino->getX() - l) *
                                  (destino->getY() - origen->getY())/
                                  (destino->getX() - origen->getX())));
                      destino->setX(l);
                    }
                 //arriba
                    if((codD & codT) != 0){
                      destino->setX(destino->getX() -
                                 ( (destino->getY() - t) *
                                  (destino->getX() - origen->getX()) /
                                  (destino->getY() - origen->getY())));
                      destino->setY(t);
                    }
                 //derecha
                    if((codD & codR) != 0){
                      destino->setY(destino->getY() -
                                 ( (destino->getX() - r) *
                                  (destino->getY() - origen->getY()) /
                                  (destino->getX() - origen->getX())));
                      destino->setX(r);
                    }
                 //abajo
                    if((codD & codB) != 0){
                       destino->setX(destino->getX() -
                                 ( (destino->getY() - b) *
                                  (destino->getX() - origen->getX()) /
                                  (destino->getY() - origen->getY())));
                      destino->setY(b);
                    }
              }
              codD = codigoCohen(destino,l,t,r,b);

        }
         }
         catch (EInvalidOp &exception){
                return false;
        }

        return false;
}

GLubyte Linea::codigoCohen(PV * punto, GLfloat l,GLfloat t,GLfloat r,GLfloat b){
      GLubyte cod = 0;

      if(punto->getX() < l){
                cod = cod | 8;
        }
        if(punto->getY() > t){
                cod = cod | 4;
        }
        if(punto->getX() > r){
                cod = cod | 2;
        }
        if(punto->getY() < b){
                cod= cod | 1;
        }

        return cod;
}
